﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[assembly: WebResource("EnhancedWebControls.ClientScripts.ModalLoadingBehavior.js", "text/javascript")]
namespace EnhancedWebControls
{
    [ParseChildren(ChildrenAsProperties=true)]
    public class ModalProgressPanel : CompositeControl
    {
        #region Public Enumerators
        public enum HorizontalMessageBoxAlignment
        {
            Right = 0,
            Center = 1,
            Left = 2
        }
        public enum VerticalMessageBoxAlignment
        {
            Top = 0,
            Center = 1,
            Bottom = 2
        }
        #endregion

        #region Private Storage
        private MessageTemplate _message;
        #endregion

        #region Public Properties Storage
        [PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(MessageTemplate)), TemplateInstance(TemplateInstance.Single)]
        public ITemplate MessageContent { get; set; }
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public ModalTriggerCollection ModalTriggers { get; private set; }
        public string OverlayCssClass { get; set; }
        public string ModalContentClientId { get; set; }
        public string ProgressDivId { get; set; }
        public VerticalMessageBoxAlignment MessageVerticalAlignment { get; set; }
        public HorizontalMessageBoxAlignment MessageHorizontalAlignment { get; set; }
        public int MessageVerticalOffset { get; set; }
        public int MessageHorizontalOffset { get; set; }
        #endregion

        #region Overriden Methods
        public ModalProgressPanel() : base()
        {
            ModalTriggers = new ModalTriggerCollection();
            OverlayCssClass = null;
            MessageVerticalAlignment = VerticalMessageBoxAlignment.Center;
            MessageHorizontalAlignment = HorizontalMessageBoxAlignment.Center;
        }
        protected override void CreateChildControls()
        {
            this.Controls.Clear();
            _message = new MessageTemplate();
            _message.ID = "MessageDiv";
            ITemplate template = MessageContent;
            template.InstantiateIn(_message);
            Controls.Add(_message);
        }
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (string.IsNullOrEmpty(this.ModalContentClientId))
            {
                throw new Exception("You must supply a ModalContentClientId");
            }
            Page.ClientScript.RegisterClientScriptResource(this.GetType(), "EnhancedWebControls.ClientScripts.ModalLoadingBehavior.js");
            if (!Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "ModalLoadingInitScript"))
                Page.ClientScript.RegisterStartupScript(this.GetType(), "ModalLoadingInitScript", "Sys.Application.add_init(InitModalLoading);", true);
        }
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            writer.AddAttribute("id", this.ClientID);
            writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "absolute");
            writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            RenderOverlayDiv(writer);
        }
        public override void RenderEndTag(HtmlTextWriter writer)
        {
            ParseTargetControls();
            writer.RenderEndTag();
            RenderClientInitScripts();
        }
        #endregion

        #region Helper Methods
        private void RenderOverlayDiv(HtmlTextWriter writer)
        {
            writer.AddAttribute("id", this.ClientID + "_OverlayDiv");
            if (!string.IsNullOrEmpty(OverlayCssClass))
                writer.AddAttribute("class", OverlayCssClass);
            else
            {
                writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
                writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, "white");
                writer.AddStyleAttribute(HtmlTextWriterStyle.Filter, "alpha(opacity=65)");
                writer.AddStyleAttribute("Opacity", "0.65");
            }

            writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.RenderEndTag();
        }
        private void ParseTargetControls()
        {
            foreach (string controlId in ModalTriggers.Where(x=>!string.IsNullOrEmpty(x.ControlId)).Select(x => x.ControlId).ToArray())
            {
                Control trigger = GetControl(Page, controlId);
                ModalTrigger item = ModalTriggers.Single(x => x.ControlId == controlId);
                item.ControlClientId = trigger.ClientID;
                item.ControlUniqueId = trigger.UniqueID;
                RecursiveAddChildControlsToTargets(trigger);
            }
        }
        private void RecursiveAddChildControlsToTargets(Control trigger)
        {
            if (trigger.HasControls())
            {
                foreach (Control c in trigger.Controls)
                {
                    if (c.Visible)
                    {
                        if (!string.IsNullOrEmpty(c.ID ))
                        {
                                if (c is IPostBackDataHandler || c is IPostBackEventHandler)
                                {
                                    ModalTriggers.Add(new ModalTrigger
                                    {
                                        ControlClientId = c.ClientID,
                                        ControlId = c.ID,
                                        ControlUniqueId = c.UniqueID
                                    });
                                }
                        }
                        if (c.HasControls())
                        {
                            RecursiveAddChildControlsToTargets(c);
                        }
                    }
                }
            }

        }
        private void RenderClientInitScripts()
        {
            string ModalLoadingBehaviorScriptKey = this.ClientID + "ModalLoadingBehaviorScriptInit";
            if (!Page.ClientScript.IsStartupScriptRegistered(this.GetType(), ModalLoadingBehaviorScriptKey))
            {
                StringBuilder script = new StringBuilder();
                foreach (ModalTrigger mcs in ModalTriggers)
                {
                    StringBuilder triggerScript = new StringBuilder();
                    triggerScript.Append("AddModalEventArgs(");
                    triggerScript.Append("\"" + mcs.ControlClientId + "\", "); //ClientId
                    triggerScript.Append("\"" + mcs.ControlUniqueId + "\", "); //UniqueId
                    triggerScript.Append("\"" + this.ClientID + "\", "); //ContainerDiv
                    triggerScript.Append("\"" + ModalContentClientId + "\", "); //ContentDiv
                    if (!string.IsNullOrEmpty(ProgressDivId))
                        triggerScript.Append("\"" + ProgressDivId + "\", "); //ProgressDiv
                    else
                        triggerScript.Append("null, "); //ProgressDiv
                    triggerScript.Append(Page.Request.Browser.IsBrowserIE6orLower().ToString().ToLower() + ", "); //hideDropDowns
                    triggerScript.Append("\"" + MessageVerticalAlignment.ToString() + "\", "); //verticalAlignment
                    triggerScript.Append("\"" + MessageHorizontalAlignment.ToString() + "\", "); //horizontaAlignment
                    triggerScript.Append(MessageVerticalOffset.ToString() + ", "); //verticalOffset
                    triggerScript.Append(MessageHorizontalOffset.ToString() + ");"); //horizontalOffset
                    script.AppendLine(triggerScript.ToString());
                }
                ScriptManager.RegisterStartupScript(this,this.GetType(), ModalLoadingBehaviorScriptKey, script.ToString(), true);
            }
        }        
        private Control GetControl(Control startControl, string controlId)
        {
            string[] sarray = controlId.Split('.');
            Control returnControl = startControl;
            foreach (string s in sarray)
            {
                returnControl = returnControl.RecursiveFindControl(s);
            }
            if (returnControl == null)
                throw new Exception("Control Not Found: " + controlId);

            return returnControl;
        }
        #endregion
    }
}
